#include "AACSource.h"
#include <iostream>
#include <chrono>

namespace jlh
{
	AACSource* AACSource::CreateNew(uint32_t samplerate, uint32_t channels, bool has_adts)
	{
		return new AACSource(samplerate, channels, has_adts);
	}

	AACSource::AACSource(uint32_t samplerate, uint32_t channels, bool has_adts)
		: samplerate_(samplerate)
		, channels_(channels)
		, has_adts_(has_adts)
	{
		payload_ = 97;
		media_type_ = AAC;
		clock_rate_ = samplerate;
	}

	AACSource::~AACSource()
	{

	}

	std::string AACSource::GetMediaDescription(uint16_t port)
	{
		char buf[128] = { 0 };
		sprintf_s(buf, 128, "m=audio %hu RTP/AVP 97", port);
		return std::string(buf);
	}

	static uint32_t AACSampleRate[16] = {
		97000,88200,64000,48000,
		44100,32000,24000,22050,
		16000,12000,11025,8000,
		7350,0,0,0
	};

	std::string AACSource::GetAttribute()
	{
		char buf[256] = { 0 };
		sprintf_s(buf, sizeof(buf), "a=rtpmap:97 MPEG4-GENERIC/%u/%u\r\n", samplerate_, channels_);

		uint8_t index = 0;
		for (index = 0; index < 16; ++index)
		{
			if (samplerate_ == AACSampleRate[index])
				break;
		}

		if (16 == index)
			return "";

		uint8_t profile = 1;
		char config[16] = { 0 };
		sprintf_s(config, "%02x%02x", (uint8_t)((profile + 1) << 3) | (index >> 1), (uint8_t)((index << 7) | (channels_ << 3)));
		sprintf_s(buf + strlen(buf),sizeof(buf)-strlen(buf),
			"a=fmtp:97 profile-level-id=1;"
			"mode=AAC-hbr;"
			"sizelength=13;indexlength=3;indexdeltalength=3;"
			"config=%04u",
			atoi(config));
		std::cout << "AACSOURCE-ATTRIBUTE:" << buf << "-LENGTH." << strlen(buf) << std::endl;
		return std::string(buf, strlen(buf));
	}
	bool AACSource::HandleFrame(MediaChannelId channelId, AVFrame frame)
	{
		std::cout << "*" << std::flush;
		if ((MAX_RTP_PAYLOAD_SIZE - AU_SIZE) < frame.size)
		{
			return false;
		}

		int adts_size = 0;
		if (has_adts_) {
			adts_size = ADTS_SIZE;
		}

		if (0 == frame.timestamp)
		{
			frame.timestamp = GetTimestamp(samplerate_);
		}

		uint8_t* frame_buf = frame.buffer.get() + adts_size;
		uint32_t frame_size = frame.size - adts_size;
		char AU[AU_SIZE] = { 0 };
		AU[0] = 0x00;
		AU[1] = 0x10;
		AU[2] = (frame_size & 0x1fe0) >> 5;
		AU[3] = (frame_size & 0x1f) << 3;
		RtpPacket rp;
		rp.type = frame.type;
		rp.timestamp = frame.timestamp;
		rp.size = frame_size + 4 + RTP_HEADER_SIZE + AU_SIZE;
		rp.last = 1;
		rp.data.get()[4 + RTP_HEADER_SIZE + 0] = AU[0];
		rp.data.get()[4 + RTP_HEADER_SIZE + 1] = AU[1];
		rp.data.get()[4 + RTP_HEADER_SIZE + 2] = AU[2];
		rp.data.get()[4 + RTP_HEADER_SIZE + 3] = AU[3];
		memcpy(rp.data.get() + 4 + RTP_HEADER_SIZE + AU_SIZE, frame_buf, frame_size);
		if (send_frame_callback_) {
			return send_frame_callback_(channelId, rp);
		}

		return false;
	}

    //把微妙单位的系统时钟转换为samplerate单位的时间戳
    //1. System.ticks * (1/10^6) = Rtp.ts * (1/samplerate)
    //2. Rtp.ts = System.ticks/10^6 * samplerate
    //3. Rtp.ts = System.ticks / 1000 * samplerate / 1000
	uint32_t AACSource::GetTimestamp(uint32_t samplerate)
	{//now()为当前系统时钟,单调递增，不受系统时间的影响，即使系统时间被篡改.
		auto time_point = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::steady_clock::now());
		return (uint32_t)((time_point.time_since_epoch().count() + 500) / 1000 * samplerate / 1000);
	}
}
